﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using knfUpdateDataLayer;
using knfUpdateDataLayer.Aggiornamento;

namespace knfProceduraAggiornamento
{
    public class ProceduraImportExport
    {
        private knfEntities  _db;

        public ProceduraImportExport()
        {
            _db = new knfEntities();
        }


     

        public bool ProceduraInCorso()
        {
            var localData = from p in _db.Procedura_Update where p.procedura_status == false select p;

            if (localData.ToList().Count > 0)
            {
                return true;
            }
            else
            {
                return false;
            }

        }


        private  List<String> DammiListaNazioni(List<RawData> listaInput)
        {

            var nazioni = (from p in listaInput select p.REPORTER_LAB).Distinct();

            return nazioni.ToList();

        }

        private static Boolean isNewRawData(RawData riga, List<RawData> listaInput)
        {

            var cerca2 = from p in listaInput
                         where
                             p.PARTNER_LAB.Trim() == riga.PARTNER_LAB.Trim() &
                             p.PRODUCT == riga.PRODUCT &
                             p.FLOW == riga.FLOW &
                             p.PERIOD == riga.PERIOD &
                             p.INDICATORS.Trim() == riga.INDICATORS.Trim()
                         select p;


            if (cerca2.Count() == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }



        private List<RawData> RigheNazioneDaDatabase(string Nazione, List<RawData> listaInputDatabase)
        {
            var cerca = (from p in listaInputDatabase where p.REPORTER_LAB.Trim() == Nazione select p);
            return cerca.ToList();
        }



        private List<RawData> RigheNazioneDaFile(string Nazione, List<RawData> listaInput)
        {
            var righe = from p in listaInput where p.REPORTER_LAB == Nazione select p;
            return righe.ToList();
        }





        public void AnalizzaFilediInput(string _fileInputPath)
        {
            List<RawData> ListaRigheLette = new List<RawData>();

            int icounter = 0;

            try
            {
                ListaRigheLette = LeggiFileInput(_fileInputPath);
                ScriviNelDb("LOADING", "Number of Rows: " + ListaRigheLette.Count.ToString());

                int AnnoMinimo = EstraiAnnoMinimoDaFile(ListaRigheLette);
                int AnnoMassimo = EstraiAnnoMassimoDaFile(ListaRigheLette);

                ScriviNelDb("LOADING", "Data from Year: " + AnnoMinimo.ToString() + " to Year: " + AnnoMassimo.ToString());

                List<RawData> ListaDatabase = new List<RawData>();
                ListaDatabase = LeggiDatabase(AnnoMinimo, AnnoMassimo);

                List<String> Nazioni = new List<string>();
                Nazioni = DammiListaNazioni(ListaRigheLette);

                List<RawData> NuoveRighe = new List<RawData>();

                foreach (string nazione in Nazioni)
                {
                    Console.WriteLine(nazione);
                    //Estraiamo SottoLista delle righe
                    List<RawData> sottoListaInput = new List<RawData>();
                    sottoListaInput = RigheNazioneDaFile(nazione, ListaRigheLette);

                    List<RawData> sottoListaDatabase = new List<RawData>();
                    sottoListaDatabase = RigheNazioneDaDatabase(nazione, ListaDatabase);


                    foreach (RawData riga in sottoListaInput)
                    {
                        if (isNewRawData(riga, sottoListaDatabase) == true)
                        {
                            NuoveRighe.Add(riga);
                        }

                    }

                }

                _db.Configuration.AutoDetectChangesEnabled = false;


                foreach (RawData nuovariga in NuoveRighe)
                {
                    icounter += 1;
                    _db.RawData.Add(nuovariga);

                    if (icounter % 1000 == 0)
                    {
                        _db.SaveChanges();
                    }
                }

                _db.SaveChanges();

                ScriviNelDb("LOADING", "Actual Number of Read and Analysed Rows: " + icounter.ToString());
                ScriviNelDb("LOADING", "End Analysis");

            }
            catch (Exception ex)
            {
                string ErrorString = "Error Analysis for Row Number: " + icounter.ToString() + ". Error: " + ex.Message;
                ScriviNelDb("ERROR", ErrorString);
                throw ex;
            }
        }

        public int CreaMacroProcedura(string InputDataFile)
        {
            Procedura_Update_Macro localData = new Procedura_Update_Macro();
            localData.macro_filename = InputDataFile;
            localData.macro_start_time = System.DateTime.Now;
            int lastId = 0;

            try 
            {
                _db.Procedura_Update_Macro.Add(localData);
                _db.SaveChanges();
                lastId = localData.macro_id;
            }

            catch 
            {
                lastId = -1;
            }

            localData = null;
            return lastId;
        }

        public void ChiudiMacroProcedura(int ProceduraId)
        {

            var localProcedura = (from p in _db.Procedura_Update_Macro where p.macro_id == ProceduraId select p).First();

            localProcedura.macro_stop_time = System.DateTime.Now;

            TimeSpan ts = localProcedura.macro_stop_time.Value - localProcedura.macro_start_time.Value;


            int MinutiTotali = (int)ts.TotalMinutes;

            localProcedura.macro_timespan = "Minuti: " + MinutiTotali.ToString();

            _db.SaveChanges();

            var localRighe = from p in _db.Procedura_Update where p.procedura_status == false select p;

            foreach(Procedura_Update  tmpRiga in localRighe)
            {
                tmpRiga.procedura_status = true;
            }

            _db.SaveChanges();
        }

        public void ChiudiUltimaProceduraAperta()
        {
            var localProcedura = (from p in _db.Procedura_Update_Macro orderby p.macro_id descending select p).First();
            localProcedura.macro_stop_time = System.DateTime.Now;

            TimeSpan ts = localProcedura.macro_stop_time.Value - localProcedura.macro_start_time.Value;


            int MinutiTotali = (int)ts.TotalMinutes;

            localProcedura.macro_timespan = "Minuti: " + MinutiTotali.ToString();

            _db.SaveChanges();

            var localRighe = from p in _db.Procedura_Update where p.procedura_status == false select p;

            foreach (Procedura_Update tmpRiga in localRighe)
            {
                tmpRiga.procedura_status = true;
            }

            _db.SaveChanges();
            
        }

        public string DammiUltimoMessaggio()
        {
            var lastMessage = (from p in _db.Procedura_Update orderby p.procedura_id descending select p).First();

            string ultimoMessaggio = string.Empty;
            ultimoMessaggio = lastMessage.procedura_datetime + ": " + lastMessage.procedura_sezione + ": " + lastMessage.procedura_messaggio;
            return ultimoMessaggio;


        }




        #region Private Functions

            private List<RawData> LeggiFileInput(string filePath)
        {
            try
            {
                StreamReader localInputFile = new StreamReader(filePath);

                string rigaLetta = string.Empty;
                List<RawData> ListaRigheLette = new List<RawData>();

                localInputFile.ReadLine();
                while (localInputFile.Peek() >= 0)
                {
                    rigaLetta = localInputFile.ReadLine();
                    string[] rigaSpezzata = null;
                    rigaSpezzata = rigaLetta.Split(new char[] { ';' });

                    RawData localObject = new RawData();

                    localObject.REPORTER_LAB = rigaSpezzata[0];
                    localObject.PARTNER_LAB = rigaSpezzata[1];
                    localObject.PRODUCT = Convert.ToDouble(rigaSpezzata[2]);
                    localObject.PRODUCT_LAB = rigaSpezzata[3];
                    localObject.FLOW = Convert.ToDouble(rigaSpezzata[4]);
                    localObject.FLOW_LAB = rigaSpezzata[5];
                    localObject.PERIOD = Convert.ToDouble(rigaSpezzata[6]);
                    localObject.PERIOD_LAB = rigaSpezzata[7];
                    localObject.INDICATORS = rigaSpezzata[8];
                    localObject.INDICATORS_LAB = rigaSpezzata[9];
                    localObject.INDICATOR_VALUE = Convert.ToDouble(rigaSpezzata[10]);

                    ListaRigheLette.Add(localObject);
                }

                return ListaRigheLette;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        //    public void ScriviNelDb(string section, string message)
        //{
        //    Procedura_Update localData = new Procedura_Update();
        //    localData.procedura_sezione = section;
        //    localData.procedura_messaggio = message;
        //    localData.procedura_datetime = System.DateTime.Now;
        //    localData.procedura_status = false;
        //    _db.Procedura_Update.InsertOnSubmit(localData);
        //    _db.SubmitChanges();

        //}


            private static void ScriviNelDb(string section, string message)
            {
                ProceduraAggiornamento localProcedura = new ProceduraAggiornamento();
                localProcedura.ScriviNelDb(section, message);

                if (section == "ERROR" || section == "CLOSING")
                {
                    localProcedura.ChiudiUltimaProceduraAperta();
                }

                localProcedura = null;
            }



            private int EstraiAnnoMinimoDaFile(List<RawData> RigheLette)
        {
            int AnnoMinimo = 2015;
            foreach (RawData fileInput in RigheLette)
            {
                int period = (int)fileInput.PERIOD;
                string periodstring = period.ToString().Substring(0, 4);
                int anno = Convert.ToInt16(periodstring);
                if (anno < AnnoMinimo)
                {
                    AnnoMinimo = anno;
                }
            }

            return AnnoMinimo;

        }

            private int EstraiAnnoMassimoDaFile(List<RawData> RigheLette)
        {
            int AnnoMassimo = 2000;
            foreach (RawData fileInput in RigheLette)
            {
                int period = (int)fileInput.PERIOD;
                string periodstring = period.ToString().Substring(0, 4);
                int anno = Convert.ToInt16(periodstring);
                if (anno > AnnoMassimo)
                {
                    AnnoMassimo = anno;
                }
            }

            return AnnoMassimo;

        }

            private  List<RawData> LeggiDatabase(int AnnoMinimo, int AnnoMassimo)
        {
            int AnnoScelto = 0;
            if (AnnoMinimo == AnnoMassimo)
            {
                AnnoScelto = AnnoMassimo;
            }
            else
            {
                AnnoScelto = AnnoMinimo;
            }


            List<RawData> listaDati = new List<RawData>();

            var leggi = from p in _db.RawData where (p.PERIOD > AnnoMinimo * 100) select p;
            listaDati = leggi.ToList();

            return listaDati;
        }

        //    private void ScriviInOutput(string filePath, string message)
        //{
        //    StreamWriter OutputFile22 = new StreamWriter(filePath);
        //    OutputFile22.WriteLine(System.DateTime.Now.ToShortDateString() + " - " + System.DateTime.Now.ToShortTimeString() + ": " +      message);
        //    OutputFile22.Close();
        //}

        #endregion


    }
}
